class CanvasUtil {

  static drawLine = (context, startX, startY, endX, endY, width = 4, color = 'blue') => {
    context.save()
    context.beginPath()
    context.moveTo(startX, startY)
    context.lineTo(endX, endY)
    context.lineWidth = width
    context.strokeStyle = color
    context.fillStyle = color
    context.stroke()
    context.fill()
    context.restore()
  }

  static drawDemo = (context) => {
    context.fillStyle = '#FF0000'
    context.fillRect(0, 0, 150, 150)
  }

  static resizeCanvas = (canvas, boardSize = 60, menuSize = 180) => {
    // 面包屑 60， 手风琴180
    canvas.width = window.innerWidth - menuSize - 40
    canvas.height = window.innerHeight - boardSize - 40

    // window.canvasWidth = canvas.width
    // window.canvasHeight = canvas.height
  }

  static drawText = (context, text, x, y, fontSize = 10, color = 'black', textAlign = 'left', angle = 0) => {
    context.save()
    context.translate(x, y)
    context.rotate(angle)
    context.textAlign = textAlign
    context.textBaseline = 'middle'
    context.fillStyle = color
    let font = '' + fontSize + 'px' + ' Arial'
    context.font = font
    context.fillText(text, 0, 0)
    context.restore()
  }

// static traslate = (context, x, y, drawShape) => {
//   context.save()
//   drawShape(context)
//   context.restore()
// }

  static pathText = (context, text, fontSize = 10, color = 'black', textAlign) => {
    context.save()
    context.textAlign = textAlign
    context.textBaseline = 'middle'
    context.fillStyle = color
    let font = '' + fontSize + 'px' + ' Arial'
    context.font = font
    context.fillText(text, 0, 0)
    context.restore()
  }

  static drawTextCenter = (context, text, x, y, fontSize = 10, color = 'black', angle = 0) => {
    CanvasUtil.drawText(context, text, x, y, fontSize, color, 'center', angle)
  }

  static cleanCanvas = (canvas) => {
    let context = canvas.getContext('2d')
    context.clearRect(0, 0, canvas.width, canvas.height)
  }

  static drawFlashLine = (canvas, context, mapInfo, mouseX = 0, mouseY = 0, iconSize = 40, fontSize = 20) => {
    let flashLines = mapInfo.flashLines

    flashLines.forEach(flashLine => {
      flashLine = CanvasUtil.flashLineUpdate(flashLine)
      CanvasUtil.flashLineDraw(flashLine, context, 'blue')
    })
  }

// 将相对于窗口的鼠标坐标转换为canvas坐标
  static windowToCanvas = (canvas, x, y) => {
    let boundingClientRect = canvas.getBoundingClientRect()
    return {
      x: x - boundingClientRect.left,
      y: y - boundingClientRect.top
    }
  }

  static strokeArc = (context, x, y, radius = 50, from = 0, to = 2, strokeStyle = "green") => {
    context.save()
    context.translate(x, y)
    context.beginPath()
    context.strokeStyle = strokeStyle;
    context.arc(0, 0, radius, from * Math.PI, to * Math.PI)
    context.stroke()
    context.restore()
  }

  static fillArc = (context, x, y, radius = 50, from = 0, to = 2 * Math.PI, fillStyle = "green") => {
    context.save()
    context.translate(x, y)
    context.beginPath()
    context.fillStyle = fillStyle;
    context.arc(0, 0, radius, from * Math.PI, to * Math.PI)
    context.fill()
    context.closePath()
    context.restore()
  }

  static fillRect = (context, x, y, width, height, fillStyle = "green") => {
    context.save()
    context.translate(x, y)
    context.beginPath()
    context.fillStyle = fillStyle
    context.fillRect(0, 0, width, height)
    context.restore()
  }

  static flashLineInit = (flashLine) => {
    let fps = flashLine.fps ? flashLine.fps : 10
    let v = flashLine.v ? flashLine.v : 20
    let angle = Math.atan2(flashLine.endY - flashLine.startY, flashLine.endX - flashLine.startX)
    let vX = v * Math.cos(angle)
    let vY = v * Math.sin(angle)
    flashLine = {
      ...flashLine,
      angle,
      vX,
      vY
    }
    let timePerFps = 1 / fps
    let moveDsPerFps = v * timePerFps
    let moveSxPerFps = vX * timePerFps
    let moveSyPerFps = vY * timePerFps
    flashLine = {
      ...flashLine,
      moveDsPerFps,
      moveSxPerFps,
      moveSyPerFps
    }

    let lines = []
    let startX = flashLine.startX
    let startY = flashLine.startY
    let endX = flashLine.endX
    let endY = flashLine.endY
    let lineLength = flashLine.lineLength

    let rangeLength = Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY))
    let numDashes = Math.round(rangeLength / (lineLength * 2))
    numDashes = numDashes % 2 === 0 ? numDashes : numDashes + 1
    // 调整lineLength，保证一定可以除尽
    // lineLength = rangeLength / numDashes
    let lineLengthX = (endX - startX) / numDashes
    let lineLengthY = (endY - startY) / numDashes

    for (let i = 0; i < numDashes; i = i + 2) {
      let startXTemp = startX + lineLengthX * i
      let startYTemp = startY + lineLengthY * i
      let endXTemp = startX + lineLengthX * (i + 1)
      let endYTemp = startY + lineLengthY * (i + 1)
      lines.push({
        startX: startXTemp,
        startY: startYTemp,
        endX: endXTemp,
        endY: endYTemp
      })
    }

    flashLine = {
      ...flashLine,
      lines,
      lineLengthX,
      lineLengthY
    }
    return flashLine
  }

  static drawDashLine = (context, startX, startY, endX, endY, lineWidth, lineLength) => {
    let lines = []

    let numDashes = Math.floor(Math.sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY)) / lineLength.lineLength)
    for (let i = 0; i < numDashes; i = i + 2) {
      let startXTemp = startX + ((endX - startX) / numDashes) * i
      let startYTemp = startY + ((endY - startY) / numDashes) * i
      let endXTemp = startX + ((endX - startX) / numDashes) * (i + 1)
      let endYTemp = startY + ((endY - startY) / numDashes) * (i + 1)
      lines.push({
        startX: startXTemp,
        startY: startYTemp,
        endX: endXTemp,
        endY: endYTemp
      })
    }

  }

  static resetPointInRange = (rangeStart, rangeEnd, x) => {
    if (rangeStart < rangeEnd) {
      if (rangeEnd < x) {
        x = rangeStart + (x - rangeEnd)
      }
    }
    if (rangeEnd < rangeStart) {
      if (x < rangeEnd) {
        x = rangeStart + (x - rangeEnd)
      }
    }
    return x
  }
  static moveInRange = (rangeStart, rangeEnd, x, moveX) => {
    x = x + moveX
    return x
  }

  static flashLineUpdate = (flashLine) => {
    let lines = flashLine.lines
    let moveSxPerFps = flashLine.moveSxPerFps
    let moveSyPerFps = flashLine.moveSyPerFps
    let startX = flashLine.startX
    let startY = flashLine.startY
    let endX = flashLine.endX
    let endY = flashLine.endY
    lines.forEach(line => {
      line.startX = CanvasUtil.moveInRange(startX, endX, line.startX, moveSxPerFps)
      line.startY = CanvasUtil.moveInRange(startY, endY, line.startY, moveSyPerFps)
      line.endX = CanvasUtil.moveInRange(startX, endX, line.endX, moveSxPerFps)
      line.endY = CanvasUtil.moveInRange(startY, endY, line.endY, moveSyPerFps)

      line.startX = CanvasUtil.resetPointInRange(startX, endX, line.startX)
      line.startY = CanvasUtil.resetPointInRange(startY, endY, line.startY)
      line.endX = CanvasUtil.resetPointInRange(startX, endX, line.endX)
      line.endY = CanvasUtil.resetPointInRange(startY, endY, line.endY)
    })

    flashLine.lines = lines
    // console.log('--------------->updateLine: ' + JSON.stringify(lines));
    return flashLine
  }

  static isOutOfRange = (rangeStart, rangeEnd, start, end) => {
    if (rangeStart < rangeEnd && end < start) {
      return true
    }
    if (rangeEnd < rangeStart && start < end) {
      return true
    }
    return false
  }

// >line:[{"startX":0,"startY":0,"endX":6.666666666666667,"endY":5},{"startX":13.333333333333334,"startY":10,"endX":20,"endY":15},{"startX":26.666666666666668,"startY":20,"endX":33.333333333333336,"endY":25}]
//    [{"startX":32,"startY":24,"endX":38.666666666666664,"endY":29},{"startX":5.333333333333336,"startY":4,"endX":12,"endY":9},{"startX":18.66666666666667,"startY":14,"endX":25.333333333333343,"endY":19}]
//   [{"startX":24,"startY":18,"endX":30.666666666666657,"endY":23},{"startX":37.333333333333336,"startY":28,"endX":4,"endY":3},{"startX":10.666666666666671,"startY":8,"endX":17.333333333333343,"endY":13}]
//   [{"startX":16,"startY":12,"endX":22.666666666666657,"endY":17},{"startX":29.333333333333343,"startY":22,"endX":36,"endY":27},{"startX":2.6666666666666714,"startY":2,"endX":9.333333333333343,"endY":7}]
//   [{"startX":8,"startY":6,"endX":14.666666666666657,"endY":11},{"startX":21.333333333333343,"startY":16,"endX":28,"endY":21},{"startX":34.66666666666667,"startY":26,"endX":1.3333333333333428,"endY":1}]
//   [{"startX":40,"startY":30,"endX":6.666666666666657,"endY":5},{"startX":13.333333333333343,"startY":10,"endX":20,"endY":15},{"startX":26.66666666666667,"startY":20,"endX":33.33333333333334,"endY":25}]
//   [{"startX":32,"startY":24,"endX":38.66666666666666,"endY":29},{"startX":5.333333333333343,"startY":4,"endX":12,"endY":9},{"startX":18.66666666666667,"startY":14,"endX":25.333333333333343,"endY":19}]
//   [{"startX":24,"startY":18,"endX":30.666666666666657,"endY":23},{"startX":37.33333333333334,"startY":28,"endX":4,"endY":3},{"startX":10.666666666666671,"startY":8,"endX":17.333333333333343,"endY":13}]

  // [{"startX":87.33333333333334,"startY":78,"rangeEndX":90,"rangeEndY":80},{"rangeStartX":50,"rangeStartY":50,"endX":54,"endY":53}]

  static getLinesInRange = (rangeStartX, rangeStartY, rangeEndX, rangeEndY, startX, startY, endX, endY) => {
    let isOutOfRangeX = CanvasUtil.isOutOfRange(rangeStartX, rangeEndX, startX, endX)
    let isOutOfRangeY = CanvasUtil.isOutOfRange(rangeStartY, rangeEndY, startY, endY)
    let isNeedSeparateTwoLine = isOutOfRangeX || isOutOfRangeY
    let lines = []
    if (isNeedSeparateTwoLine) {
      lines.push({
        startX,
        startY,
        endX: rangeEndX,
        endY: rangeEndY
      })
      lines.push({
        startX: rangeStartX,
        startY: rangeStartY,
        endX,
        endY
      })
    } else {
      lines.push({
        startX,
        startY,
        endX,
        endY
      })
    }
    return lines
  }

  static flashLineDraw = (flashLine, context, color) => {
    let lines = flashLine.lines
    let startX = flashLine.startX
    let startY = flashLine.startY
    let endX = flashLine.endX
    let endY = flashLine.endY
    CanvasUtil.drawLine(context, startX, startY, endX, endY, 5, 'lightGreen')
    let lineWidth = 2
    context.beginPath()
    context.strokeStyle = color
    CanvasUtil.index = CanvasUtil.index + 1
    lines.forEach((line) => {
      let x1 = line.startX
      let y1 = line.startY
      let x2 = line.endX
      let y2 = line.endY
      let subLines = CanvasUtil.getLinesInRange(startX, startY, endX, endY, x1, y1, x2, y2)
      subLines.forEach(tempLine => {
        CanvasUtil.drawLine(context, tempLine.startX, tempLine.startY, tempLine.endX, tempLine.endY, lineWidth, color)
      })
    })
  }

  static flashLineCreate = (startX, startY, endX, endY, v = 20, fps = 20) => {
    let flashLine = {
      startX,
      startY,
      endX,
      endY,
      lineLength: 5,
      v,
      fps
    }
    flashLine = CanvasUtil.flashLineInit(flashLine)
    return flashLine
  }

  /**
   * 设置div是否可见
   * @param div
   * @param visible true/false
   */
  static divSetVisible = (div, visible) => {
    if (visible) {
      div.style.display = ''
    } else {
      div.style.display = 'none'
    }
  }

  /**
   * 按照鼠标事件 重置absolute position div的位置
   * @param div
   * @param e mouseEvent
   */
  static divAbsolutePositionResetByMouseEvent = (div, x, y) => {
    div.style.left = '' + x + 'px'
    div.style.top = '' + y + 'px'
  }

  /**
   * @param div
   * @param innerHtml
   */
  static divSetInnerHTML = (div, innerHTML) => {
    div.innerHTML = innerHTML
  }

  static getNumberValue = (value) => {
    if (typeof value === 'string') {
      return parseFloat(value)
    }
    if (typeof value === 'number') {
      return value
    }
    return null
  }
}


export {CanvasUtil}
